package cn.wizzer.app.crown.modules.services.impl.order;

import cn.wizzer.app.crown.modules.models.*;
import cn.wizzer.app.crown.modules.models.constant.CrownConstant;
import cn.wizzer.app.crown.modules.models.enums.PlayWayEnum;
import cn.wizzer.app.crown.modules.models.enums.SettleStatusEnum;
import cn.wizzer.app.crown.modules.services.BKSettleService;
import cn.wizzer.app.crown.modules.services.CrownLeagueService;
import cn.wizzer.app.crown.modules.services.CrownMatchService;
import cn.wizzer.app.crown.modules.services.CrownSubResultService;
import cn.wizzer.app.crown.modules.services.order.CrownOrderDetailService;
import cn.wizzer.app.crown.modules.services.order.CrownOrderService;
import cn.wizzer.app.crown.modules.services.result.LeagueResultService;
import cn.wizzer.app.sys.modules.models.SysMsg;
import cn.wizzer.app.sys.modules.services.SysMsgService;
import cn.wizzer.app.user.modules.models.UserAccount;
import cn.wizzer.app.user.modules.models.enums.BizTypeEnum;
import cn.wizzer.app.user.modules.models.vo.UserAccountVo;
import cn.wizzer.app.user.modules.services.account.UserAccountRecordService;
import cn.wizzer.app.user.modules.services.account.UserAccountService;
import cn.wizzer.framework.base.Result;
import cn.wizzer.framework.base.exceptions.BizException;
import cn.wizzer.framework.base.service.CommonDBService;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@IocBean
@Service(interfaceClass = BKSettleService.class)
public class BKSettleServiceImpl implements BKSettleService {
    @Inject
    private CrownMatchService matchService;
    @Inject
    private CommonDBService commondbservice;
    @Inject
    private CrownOrderService orderService;
    @Inject
    private CrownLeagueService leagueService;
    @Inject
    private LeagueResultService leagueResultService;
    @Inject
    private CrownSubResultService subResultService;
    @Inject
    private CrownOrderDetailService orderDetailService;
    @Reference(retries = 0)
    @Inject
    private UserAccountRecordService recordService;
    @Inject
    @Reference
    private UserAccountService accountService;
    @Inject
    @Reference
    private SysMsgService sysMsgService;
    //    @Inject
//    @Reference
//    private WkNotifyUtil wkNotifyUtil;

    @Override
    public void settle(CrownOrder order) {
        // 单式结算
        if (PlayWayEnum.R.equals(order.getPlayWay())) {
            // 订单详情
            CrownOrderDetail orderDetail = orderDetailService.fetch(Cnd.where("order_id", "=", order.getId()));
            order.setDetails(Result.createList(orderDetail));
            // 关联赛事
            CrownMatch match = matchService.fetch(orderDetail.getGameId());
            this.simplexSettle(order, match);
        }
        // 综合结算
        else if (PlayWayEnum.P3.equals(order.getPlayWay())) {
            this.complexSettle(order);
        }
        // 冠军只能手动结算
        else if (PlayWayEnum.FS.equals(order.getPlayWay())) {
            // 查询订单详情
            CrownOrderDetail orderDetail = orderDetailService.fetch(Cnd.where("order_id", "=", order.getId()));
            order.setDetails(Result.createList(orderDetail));
            // 查询关联的联赛
            CrownLeague league = leagueService.fetch(orderDetail.getGameId());
            this.championSettle(order, league);
        }
    }

    @Override
    public void reSettle(CrownMatch match) {
        // 查询该赛事相关并且订单已经结算的orderDetail集合
        Sql sql = Sqls.create("SELECT od.* FROM crown_order_detail AS od LEFT JOIN crown_order AS o ON od.order_id = o.id")
                .appendSourceSql("WHERE o.status = @status and od.game_id = @matchId")
                .setParam("status", SettleStatusEnum.SETTLED)
                .setParam("matchId", match.getId());
        List<CrownOrderDetail> orderDetails = commondbservice.list(CrownOrderDetail.class, sql.toString());
        // 记录订单旧的输赢状态
        SettleStatusEnum oldStatus;
        // 重新计算订单输赢
        for (CrownOrderDetail orderDetail : orderDetails) {
            // 新的赛事状态是other
            if (CrownConstant.OTHER.equals(match.getStage())) {
                // 查询出订单并扣除结算金额
                CrownOrder order = this.deductResultAmount(orderDetail);
                if (PlayWayEnum.P3.equals(order.getPlayWay())) {
                    // 综合订单重新结算
                    this.complexSettle(order);
                } else {
                    orderDetail.setStatus(SettleStatusEnum.CANCELLED);
                    // 单式订单回退下注金额
                    this.handleRefundOrder(order);
                }
            }
            // 新的赛事状态是finished
            else {
                // 记录旧的订单条目结算状态
                oldStatus = orderDetail.getStatus();
                // 重新计算输赢
                this.calSimplexStatus(orderDetail, match);
                // 如果重新计算的输赢状态发生变化，重新结算该笔订单
                if (!oldStatus.equals(orderDetail.getStatus())) {
                    // 查询出订单并扣除结算金额
                    CrownOrder order = this.deductResultAmount(orderDetail);
                    if (PlayWayEnum.R.equals(order.getPlayWay())) {
                        // 单式订单重新结算
                        this.simplexSettle(order, match);
                    } else {
                        // 综合订单重新结算
                        this.complexSettle(order);
                    }
                    // 如果用户余额为负数，后台发送消息通知。
                    this.sendSysMsg(order);
                }
            }
        }

    }

    @Override
    public void reSettle(CrownLeague league) {
        // 查询该联赛下已结算的订单
        Sql sql = Sqls.create("SELECT od.* FROM crown_order_detail AS od LEFT JOIN crown_order AS o ON od.order_id = o.id")
                .appendSourceSql("WHERE o.status = @status and od.game_id = @leagueId")
                .setParam("status", SettleStatusEnum.SETTLED)
                .setParam("leagueId", league.getId());
        List<CrownOrderDetail> orderDetails = commondbservice.list(CrownOrderDetail.class, sql.toString());
        // 记录订单旧的输赢状态
        SettleStatusEnum oldStatus;
        // 重新计算订单输赢
        for (CrownOrderDetail orderDetail : orderDetails) {
            // 新的状态是other
            if (CrownConstant.OTHER.equals(league.getStage())) {
                // 查询出订单并扣除结算金额
                CrownOrder order = this.deductResultAmount(orderDetail);
                // 回退下注金额
                orderDetail.setStatus(SettleStatusEnum.CANCELLED);
                // 单式订单回退下注金额
                this.handleRefundOrder(order);
            }
            // 新的赛事状态是finished
            else {
                // 记录旧的订单条目结算状态
                oldStatus = orderDetail.getStatus();
                // 重新计算输赢
                this.calChampionStatus(orderDetail, league);
                // 如果重新结算的输赢状态不相同，则重新结算。
                if (!oldStatus.equals(orderDetail.getStatus())) {
                    // 查询出订单并扣除结算金额
                    CrownOrder order = this.deductResultAmount(orderDetail);
                    // 重新结算
                    this.championSettle(order, league);
                    // 如果用户余额为负数，后台发送消息通知。
                    this.sendSysMsg(order);
                }
            }
        }
    }


    /**
     * 查询order，并扣除结算金额
     *
     * @param orderDetail
     * @return
     */
    private CrownOrder deductResultAmount(CrownOrderDetail orderDetail) {
        CrownOrder order = orderService.fetch(orderDetail.getOrderId());
        order.setDetails(Result.createList(orderDetail));
        // 结算金额大于0则扣除
        if (order.getResultAmount().compareTo(BigDecimal.ZERO) > 0) {
            // 扣除结算金额
            recordService.add(order.getUserId(), order.getResultAmount(), BizTypeEnum.BALL_DEDUCT, order.getId());
        }
        return order;
    }


    /**
     * 查询用户账户是否为负数，发送后台消息
     * @param order
     */
    private void sendSysMsg(CrownOrder order) {
        UserAccount userAccount = accountService.selectByUserId(order.getUserId());
        if (userAccount.getTotal().compareTo(BigDecimal.ZERO) < 0) {
            Sql accountSql = Sqls.create("SELECT a.*,u.`nickName`,u.`phone` FROM user_account AS a LEFT JOIN USER AS u ON u.id = a.user_id")
                    .appendSourceSql("WHERE u.id = @userId")
                    .setParam("userId", order.getUserId());
            UserAccountVo userAccountVo = commondbservice.fetchSql(UserAccountVo.class, accountSql.toString());
            //构建消息通知
            SysMsg msg = sysMsgService.createMsg("system", "账变导致用户账户金额为负数",
                    "相关订单号:" + order.getNo() + "用户账户信息:" + userAccountVo.toString(), null);
            //插入通知
            sysMsgService.saveMsg(msg, null);
            //后台通知管理员
            //wkNotifyUtil.notify(msg, null);
        }
    }


    /**
     * 冠军订单结算
     *
     * @param order
     * @param league
     */
    @Aop(TransAop.REPEATABLE_READ)
    private void championSettle(CrownOrder order, CrownLeague league) {
        CrownOrderDetail orderDetail = order.getDetails().get(0);
        // 如果赛事状态为other，退回下注金额
        if (CrownConstant.OTHER.equals(league.getStage())) {
            orderDetail.setStatus(SettleStatusEnum.CANCELLED);
            this.handleRefundOrder(order);
        }
        // 如果赛事结束，进行结算
        else if (CrownConstant.FINISHED.equals(league.getStage())) {
            // 判断订单状态是否是第一次结算
            boolean isWaitSettle = SettleStatusEnum.WAIT_SETTLE.equals(order.getStatus());
            if (isWaitSettle) {
                // 查询最新version的联赛赛果详情
                Cnd cnd = Cnd.where("league_id", "=", league.getId()).and("version", "=", league.getVersion());
                List<CrownLeagueResult> subResults = leagueResultService.query(cnd);
                league.setSubResults(subResults);
                // 计算输赢
                this.calChampionStatus(orderDetail, league);
            }
            // 全输则‘结算金额’为0
            if (SettleStatusEnum.FULL_LOSE.equals(orderDetail.getStatus())) {
                order.setResultAmount(BigDecimal.ZERO);
            }
            // 非全输
            else {
                // 中奖则计算金额
                BigDecimal resultAmount = this.calChampionProfit(order);
                order.setResultAmount(resultAmount);
                // 判断结算状态（正常结算、重新结算）
                BizTypeEnum bizType = SettleStatusEnum.WAIT_SETTLE.equals(order.getStatus())
                        ? BizTypeEnum.BALL_RESULT : BizTypeEnum.BALL_RESETTLE;
                // 划转钻石
                recordService.add(order.getUserId(), resultAmount, bizType, order.getId());
            }
            order.setStatus(isWaitSettle ? SettleStatusEnum.SETTLED : SettleStatusEnum.RESETTLED);
            // 更新orderDetail状态
            orderDetailService.update(orderDetail);
            //设置结算时间
            order.setSettleAt(System.currentTimeMillis() / 1000);
            // 更新order结算金额和结算状态
            orderService.update(order);
        } else {
            throw new BizException("结算错误：联赛状态错误(" + league.getStage() + ")。LeagueId:" + league.getId());
        }
    }


    /**
     * 综合订单结算
     *
     * @param order
     */
    @Aop(TransAop.REPEATABLE_READ)
    private void complexSettle(CrownOrder order) {
        // 综合结算。查询出该笔订单下的orderDetail集合
        List<CrownOrderDetail> orderDetails = orderDetailService.query(Cnd.where("orderId", "=", order.getId()));
        if (orderDetails.size() < 3 || orderDetails.size() > 10) {
            throw new BizException("综合类订单结算错误，订单条目有误。数量：" + orderDetails.size() + "orderId:" + order.getId());
        }
        order.setDetails(orderDetails);
        // 赛事状态为‘other’的订单数量
        int otherStageNum = 0;
        // 订单结果是否是‘FULL_LOSE’的标记
        boolean flag = false;
        // 遍历集合结算
        for (CrownOrderDetail orderDetail : orderDetails) {
            CrownMatch match = matchService.fetch(orderDetail.getGameId());
            if (!(CrownConstant.FINISHED.equals(match.getStage()) || CrownConstant.OTHER.equals(match.getStage()))) {
                throw new BizException("结算错误：综合赛事状态错误(" + match.getStage() + ")。Mid:" + match.getId());
            }
            // 查询最新赛果详情
            Cnd cnd = Cnd.where("match_id", "=", match.getId()).and("version", "=", match.getVersion());
            // 查询最新version的赛果详情
            List<CrownSubResult> subResults = subResultService.query(cnd.orderBy("tag", "asc"));
            match.setSubResults(subResults);
            // 如果赛事是‘其他’状态
            if (CrownConstant.OTHER.equals(match.getStage())) {
                // 设置orderDetail状态为‘取消’
                orderDetail.setStatus(SettleStatusEnum.CANCELLED);
                // 记录赛事状态为‘other’的订单数量
                ++otherStageNum;
            } else if (CrownConstant.FINISHED.equals(match.getStage())) {
                // 计算订单条目输赢
                if (SettleStatusEnum.WAIT_SETTLE.equals(order.getStatus())) {
                    this.calSimplexStatus(orderDetail, match);
                }
                // 腰斩
                if (SettleStatusEnum.CANCELLED.equals(orderDetail.getStatus())) {
                    ++otherStageNum;
                }
                // 如果该订单条目为‘全输’，flag置为false
                if (SettleStatusEnum.FULL_LOSE.equals(orderDetail.getStatus())) {
                    flag = true;
                }
            } else {
                throw new BizException("综合结算错误：赛事状态错误(" + match.getStage() + ")。MID:" + match.getId());
            }
        }
        // 如果订单关联的赛事状态都是‘other’，则退回本金
        if (otherStageNum == orderDetails.size()) {
            // 回退本金
            this.handleRefundOrder(order);
        } else {
            boolean isWaitSettle = SettleStatusEnum.WAIT_SETTLE.equals(order.getStatus());
            // 不中奖将结算金额设置为0
            if (flag) {
                order.setResultAmount(BigDecimal.ZERO);
            } else {
                // 计算综合订单结算金额
                BigDecimal resultAmount = this.calComplexProfit(order);
                order.setResultAmount(resultAmount);
                // 判断结算状态（正常结算、重新结算）
                BizTypeEnum bizType;
                bizType = isWaitSettle ? BizTypeEnum.BALL_RESULT : BizTypeEnum.BALL_RESETTLE;
                // 划转钻石
                recordService.add(order.getUserId(), resultAmount, bizType, order.getId());
            }
            order.setStatus(isWaitSettle ? SettleStatusEnum.SETTLED : SettleStatusEnum.RESETTLED);
            //设置结算时间
            order.setSettleAt(System.currentTimeMillis() / 1000);
            // 更新orderDetail状态（批量更新）
            orderDetailService.update(orderDetails);
            // 更新order结算金额和结算状态
            orderService.update(order);
        }
    }


    /**
     * 单式订单结算
     *
     * @param order
     * @param match
     */
    @Aop(TransAop.REPEATABLE_READ)
    private void simplexSettle(CrownOrder order, CrownMatch match) {
        // 查找detial
        CrownOrderDetail orderDetail = order.getDetails().get(0);
        // 赛事异常，退回下注金额
        if (CrownConstant.OTHER.equals(match.getStage())) {
            orderDetail.setStatus(SettleStatusEnum.CANCELLED);
            this.handleRefundOrder(order);
        }
        // 赛事正常或半场已过则进行结算
        else if (CrownConstant.FINISHED.equals(match.getStage()) || match.getIsHalfGone()) {
            // 判断订单状态是否是第一次结算
            boolean isWaitSettle = SettleStatusEnum.WAIT_SETTLE.equals(order.getStatus());
            if (isWaitSettle) {
                // 查询最新version的赛事赛果详情
                Cnd cnd = Cnd.where("match_id", "=", match.getId()).and("version", "=", match.getVersion());
                List<CrownSubResult> subResults = subResultService.query(cnd.orderBy("tag", "asc"));
                match.setSubResults(subResults);
                // 计算输赢
                this.calSimplexStatus(orderDetail, match);
            }
            // 赛事腰斩(退款)
            if (SettleStatusEnum.CANCELLED.equals(orderDetail.getStatus())) {
                orderDetail.setStatus(SettleStatusEnum.CANCELLED);
                this.handleRefundOrder(order);
            } else {
                // 全输则‘结算金额’为0
                if (SettleStatusEnum.FULL_LOSE.equals(orderDetail.getStatus())) {
                    order.setResultAmount(BigDecimal.ZERO);
                }
                // 非全输
                else {
                    // 中奖则计算金额
                    BigDecimal resultAmount = this.calSimplexProfit(order);
                    order.setResultAmount(resultAmount);
                    // 判断结算状态（正常结算、重新结算）
                    BizTypeEnum bizType;
                    bizType = isWaitSettle ? BizTypeEnum.BALL_RESULT : BizTypeEnum.BALL_RESETTLE;
                    // 划转钻石
                    recordService.add(order.getUserId(), resultAmount, bizType, order.getId());
                }
                // 判断order状态
                order.setStatus(isWaitSettle ? SettleStatusEnum.SETTLED : SettleStatusEnum.RESETTLED);
                // 更新orderDetail状态
                orderDetailService.update(orderDetail);
                // 设置结算时间
                order.setSettleAt(System.currentTimeMillis() / 1000);
                // 更新order结算金额和结算状态
                orderService.update(order);
            }
        } else {
            throw new BizException("结算错误：赛事状态错误(" + match.getStage() + ")。MID:" + match.getMid());
        }
    }


    /**
     * 单式、综合玩法根据orderDetail no1计算输赢
     *
     * @param orderDetail
     * @param match
     */
    private void calSimplexStatus(CrownOrderDetail orderDetail, CrownMatch match) {
        // 处理赛果
        HashMap<String, CrownSubResult> subResultsMap = this.handleSubResults(match.getSubResults());
        // 计算orderDetail输赢
        // 开始结算
        switch (orderDetail.getNo1()) {
            // 全场独赢玩法
            case 1:
                this.fullCourtWinSimplex(orderDetail, subResultsMap.get("NO8"));
                break;
            // 全场让球玩法
            case 2:
                this.fullCourtLetBall(orderDetail, subResultsMap.get("NO8"));
                break;
            // 全场大小玩法
            case 3:
                this.fullCourtBigOrSmall(orderDetail, subResultsMap.get("NO8"));
                break;
            // 球队得分大玩法
            case 4:
                this.fullTeamGoalsBig(orderDetail, subResultsMap.get("NO8"));
                break;
            // 球队得分小玩法
            case 5:
                this.fullTeamGoalsSmall(orderDetail, subResultsMap.get("NO8"));
                break;
            default:
                throw new BizException("结算错误：玩法不存在！" + orderDetail.getNo1());
        }

    }


    /**
     *
     * @param orderDetail
     * @param league
     */
    private void calChampionStatus(CrownOrderDetail orderDetail, CrownLeague league) {
        // 取赛果集合中的‘冠军名’
        List<String> results = league.getSubResults()
                .stream()
                .map(CrownLeagueResult::getWinner)
                .collect(Collectors.toList());
        if (results.contains(orderDetail.getCoeWord())) {
            orderDetail.setStatus(SettleStatusEnum.FULL_WIN);
        } else {
            orderDetail.setStatus(SettleStatusEnum.FULL_LOSE);
        }
    }

    /**
     * 处理退款订单
     *
     * @param order
     */
    private void handleRefundOrder(CrownOrder order) {
        List<CrownOrderDetail> orderDetails = order.getDetails();
        if (SettleStatusEnum.WAIT_SETTLE.equals(order.getStatus())) {
            order.setStatus(SettleStatusEnum.CANCELLED);
        }
        // 更新orderDetail状态（如果是综合订单会批量更新所有的订单条目）
        orderDetailService.update(orderDetails);
        // 设置结算时间
        order.setSettleAt(System.currentTimeMillis() / 1000);
        // 更新order结算金额和结算状态
        orderService.update(order);
        // 判断结算状态（正常结算、重新结算）
        BizTypeEnum status = SettleStatusEnum.WAIT_SETTLE.equals(order.getStatus())
                ? BizTypeEnum.BALL_REVERT : BizTypeEnum.BALL_RESETTLE;
        // 钻石划转
        recordService.add(order.getUserId(), order.getAmount(), status, order.getId());
    }


    /**
     * 处理赛果详情数据，将list转为map，key为subResult对象的tag(NO1、NO2...)
     *
     * @param subResults
     * @return
     */
    private HashMap<String, CrownSubResult> handleSubResults(List<CrownSubResult> subResults) {
        HashMap<String, CrownSubResult> map = new HashMap<>(subResults.size());
        for (CrownSubResult subResult : subResults) {
            map.put(subResult.getTag(), subResult);
        }
        return map;
    }


    /**
     * 处理分数
     *
     * @param orderDetail
     * @param subResult
     * @return
     */
    private Map<String, Integer> handleScores(CrownOrderDetail orderDetail, CrownSubResult subResult) {
        if (subResult.getResultH().contains("腰斩") || subResult.getResultC().contains("腰斩")) {
            orderDetail.setStatus(SettleStatusEnum.CANCELLED);
            return null;
        } else {
            Map<String, Integer> scoreMap = new HashMap<>();
            scoreMap.put("H", Integer.parseInt(subResult.getResultH()));
            scoreMap.put("C", Integer.parseInt(subResult.getResultC()));
            return scoreMap;
        }
    }


    /**
     * 全场独赢玩法结算
     *
     * @param orderDetail
     * @param subResult
     */
    private void fullCourtWinSimplex(CrownOrderDetail orderDetail, CrownSubResult subResult) {
        Map<String, Integer> scoresMap = this.handleScores(orderDetail, subResult);
        if (null != scoresMap) {
            this.courtWin(orderDetail, scoresMap.get("H"), scoresMap.get("C"));
        }
    }


    /**
     * 独赢玩法计算
     *
     * @param orderDetail
     * @param mbInBall
     * @param tgInBall
     */
    private void courtWin(CrownOrderDetail orderDetail, int mbInBall, int tgInBall) {
        // no3是下注的内容
        int no3 = orderDetail.getNo3();
        // 如果no3 = 1 主队比分 > 客队比分 中奖
        if (1 == no3 && (mbInBall > tgInBall)) {
            orderDetail.setStatus(SettleStatusEnum.FULL_WIN);
        }
        // 如果no3 = 2 客队比分 > 主队比分 中奖
        else if (2 == no3 && (mbInBall > tgInBall)) {
            orderDetail.setStatus(SettleStatusEnum.FULL_WIN);
        }
        // 否则 输
        else {
            orderDetail.setStatus(SettleStatusEnum.FULL_LOSE);
        }
    }


    /**
     * 全场让球玩法结算
     *
     * @param orderDetail
     * @param subResult
     */
    private void fullCourtLetBall(CrownOrderDetail orderDetail, CrownSubResult subResult) {
        Map<String, Integer> scoresMap = this.handleScores(orderDetail, subResult);
        if (null != scoresMap) {
            // 计算输赢
            this.courtLetBall(orderDetail, scoresMap.get("H"), scoresMap.get("C"));
        }
    }


    /**
     * 让球玩法计算
     *
     * @param orderDetail
     * @param mbInBall
     * @param tgInBall
     */
    private void courtLetBall(CrownOrderDetail orderDetail, int mbInBall, int tgInBall) {
        // 获取下注的点
        int no3 = orderDetail.getNo3();
        boolean mbIsStrong = (1 == orderDetail.getNo3() && !orderDetail.getCoeNum().contains("-"))
                || (2 == orderDetail.getNo3() && orderDetail.getCoeNum().contains("-"));
        // 主队是强队
        if (mbIsStrong) {
            // 篮球是单系数
            double coeNum = Math.abs(Double.parseDouble(orderDetail.getCoeNum()));
            // 主队得分 - 客队得分 - 系数 > 0
            if (mbInBall - tgInBall - coeNum > 0) {
                // 下注主队 全赢
                if (1 == no3) {
                    orderDetail.setStatus(SettleStatusEnum.FULL_WIN);
                } else {
                    // 下注客队 全输
                    orderDetail.setStatus(SettleStatusEnum.FULL_LOSE);
                }
            }
            // 主队得分 - 客队得分 - 系数 = 0
            else if (mbInBall - tgInBall - coeNum == 0) {
                // 下注主队 走水.下注客队 走水
                orderDetail.setStatus(SettleStatusEnum.GO_WATER);
            }
            // 主队得分 - 客队得分 - 系数 < 0
            else {
                // 下注主队 全输
                if (1 == no3) {
                    orderDetail.setStatus(SettleStatusEnum.FULL_LOSE);
                } else {
                    // 下注客队 全赢
                    orderDetail.setStatus(SettleStatusEnum.FULL_WIN);
                }
            }
        } else {
            // 客队是强队
            // 单系数
            double coeNum = Math.abs(Double.parseDouble(orderDetail.getCoeNum()));
            // 客队得分 - 主队得分 - 系数 > 0
            if (tgInBall - mbInBall - coeNum > 0) {
                // 下注客队 全赢
                if (2 == no3) {
                    orderDetail.setStatus(SettleStatusEnum.FULL_WIN);
                } else {
                    // 下注主队 全输
                    orderDetail.setStatus(SettleStatusEnum.FULL_LOSE);
                }
            }
            // 客队得分 - 主队得分 - 系数 = 0
            else if (tgInBall - mbInBall - coeNum == 0) {
                // 下注主队 走水.下注客队 走水
                orderDetail.setStatus(SettleStatusEnum.GO_WATER);
            }
            // 客队得分 - 主队得分 - 系数 < 0
            else {
                // 下注客队 全输
                if (2 == no3) {
                    orderDetail.setStatus(SettleStatusEnum.FULL_LOSE);
                } else {
                    // 下注主队 全赢
                    orderDetail.setStatus(SettleStatusEnum.FULL_WIN);
                }
            }
        }
    }


    /**
     * 全场大小玩法结算
     *
     * @param orderDetail
     * @param subResult
     */
    private void fullCourtBigOrSmall(CrownOrderDetail orderDetail, CrownSubResult subResult) {
        Map<String, Integer> scoresMap = this.handleScores(orderDetail, subResult);
        if (null != scoresMap) {
            this.courtBigOrSmall(orderDetail, scoresMap.get("H"), scoresMap.get("C"));
        }
    }


    /**
     * 大小玩法计算输赢
     *
     * @param orderDetail
     * @param mbInBall
     * @param tgInBall
     */
    private void courtBigOrSmall(CrownOrderDetail orderDetail, int mbInBall, int tgInBall) {
        // 获取下注的点
        int no3 = orderDetail.getNo3();
        // 全场得分 = 主队全场得分 + 客队全场得分
        int fullInBall = mbInBall + tgInBall;
        // 篮球的都是单系数
        double coeNum = Double.parseDouble(orderDetail.getCoeNum());
        // 如果全场得分大于系数
        if (fullInBall > coeNum) {
            // 下注no3=1的位置 全赢
            if (1 == no3) {
                orderDetail.setStatus(SettleStatusEnum.FULL_WIN);
            } else {
                // no3=2的位置 全输
                orderDetail.setStatus(SettleStatusEnum.FULL_LOSE);
            }
        }
        // 如果全场得分小于系数
        else if (fullInBall < coeNum) {
            // 下注no3=1的位置 全输
            if (1 == no3) {
                orderDetail.setStatus(SettleStatusEnum.FULL_LOSE);
            } else {
                // no3=2的位置 全赢
                orderDetail.setStatus(SettleStatusEnum.FULL_WIN);
            }
        }
        // 如果全场得分等于系数，走水。
        else {
            orderDetail.setStatus(SettleStatusEnum.GO_WATER);
        }
    }


    /**
     * 全场球队得分大
     *
     * @param orderDetail
     * @param subResult
     */
    private void fullTeamGoalsBig(CrownOrderDetail orderDetail, CrownSubResult subResult) {
        Map<String, Integer> scoresMap = this.handleScores(orderDetail, subResult);
        if (null != scoresMap) {
            this.teamGoalsBig(orderDetail, scoresMap.get("H"), scoresMap.get("C"));
        }
    }

    /**
     * 球队得分大计算
     *
     * @param orderDetail
     * @param mbInBall
     * @param tgInBall
     */
    private void teamGoalsBig(CrownOrderDetail orderDetail, int mbInBall, int tgInBall) {
        // 获取下注的点
        int no3 = orderDetail.getNo3();
        // 系数
        double coeNum = Math.abs(Double.parseDouble(orderDetail.getCoeNum()));
        // 如果下注的是主队
        if (1 == no3) {
            // 如果主队比分大于系数 全赢
            if (mbInBall > coeNum) {
                orderDetail.setStatus(SettleStatusEnum.FULL_WIN);
            }
            // 否则如果主队比分等于系数 走水
            else if (mbInBall == coeNum) {
                orderDetail.setStatus(SettleStatusEnum.GO_WATER);
            }
            // 否则(主队比分小于系数) 全输
            else {
                orderDetail.setStatus(SettleStatusEnum.FULL_LOSE);
            }
        } else {
            // 如果客队比分大于系数 全赢
            if (tgInBall > coeNum) {
                orderDetail.setStatus(SettleStatusEnum.FULL_WIN);
            }
            // 否则如果客队比分等于系数 走水
            else if (tgInBall == coeNum) {
                orderDetail.setStatus(SettleStatusEnum.GO_WATER);
            }
            // 否则(客队比分小于系数) 全输
            else {
                orderDetail.setStatus(SettleStatusEnum.FULL_LOSE);
            }
        }
    }

    /**
     * 球队得分小
     *
     * @param orderDetail
     * @param subResult
     */
    private void fullTeamGoalsSmall(CrownOrderDetail orderDetail, CrownSubResult subResult) {
        Map<String, Integer> scoresMap = this.handleScores(orderDetail, subResult);
        if (null != scoresMap) {
            // 计算输赢
            this.teamGoalsSmall(orderDetail, scoresMap.get("H"), scoresMap.get("C"));
        }
    }

    /**
     * 球队进球小
     *
     * @param orderDetail
     * @param mbInBall
     * @param tgInBall
     */
    private void teamGoalsSmall(CrownOrderDetail orderDetail, int mbInBall, int tgInBall) {
        // 获取下注的点
        int no3 = orderDetail.getNo3();
        // 系数
        double coeNum = Math.abs(Double.parseDouble(orderDetail.getCoeNum()));
        // 如果下注的是主队
        if (1 == no3) {
            // 如果主队比分小于系数 全赢
            if (mbInBall < coeNum) {
                orderDetail.setStatus(SettleStatusEnum.FULL_WIN);
            }
            // 否则如果主队比分等于系数 走水
            else if (mbInBall == coeNum) {
                orderDetail.setStatus(SettleStatusEnum.GO_WATER);
            }
            // 否则(主队比分大于系数) 全输
            else {
                orderDetail.setStatus(SettleStatusEnum.FULL_LOSE);
            }
        } else {
            // 如果客队比分小于系数 全赢
            if (tgInBall < coeNum) {
                orderDetail.setStatus(SettleStatusEnum.FULL_WIN);
            }
            // 否则如果客队比分等于系数 走水
            else if (tgInBall == coeNum) {
                orderDetail.setStatus(SettleStatusEnum.GO_WATER);
            }
            // 否则(客队比分大于系数) 全输
            else {
                orderDetail.setStatus(SettleStatusEnum.FULL_LOSE);
            }
        }
    }


    /**
     * 单式金额计算
     * 中奖（可赢+本金）
     * 不中奖 0
     *
     * @param order
     * @return
     */
    private BigDecimal calSimplexProfit(CrownOrder order) {
        CrownOrderDetail orderDetail = order.getDetails().get(0);
        BigDecimal amount = order.getAmount();
        BigDecimal odds = orderDetail.getOdds();
        int no1 = orderDetail.getNo1();
        // 让球、总得分大小、球队得分大小赔率要加一。因为要返回本金
        if (2 == no1 || 3 == no1 || 4 == no1 || 5 == no1) {
            odds = odds.add(BigDecimal.ONE);
        }
        // 根据orderDetail的状态计算金额
        switch (orderDetail.getStatus()) {
            case FULL_WIN:
                // 全赢：本金 * 赔率
                amount = amount.multiply(odds);
                break;
            case GO_WATER:
                // 走水，amount = amount
                break;
            default:
                throw new BizException("结算错误：类型错误" + orderDetail.getStatus());
        }
        return amount;
    }

    /**
     * 综合金额计算
     *
     * @param order
     * @return
     */
    private BigDecimal calComplexProfit(CrownOrder order) {
        List<CrownOrderDetail> orderDetailList = order.getDetails();
        // 下注金额
        BigDecimal amount = order.getAmount();
        for (CrownOrderDetail orderDetail : orderDetailList) {
            // 根据orderDetail的状态计算金额
            switch (orderDetail.getStatus()) {
                case FULL_WIN:
                    // 全赢：本金 * 赔率
                    amount = amount.multiply(orderDetail.getOdds());
                    break;
                case CANCELLED:
                case GO_WATER:
                    // 走水，amount = amount
                    break;
                default:
                    throw new BizException("结算错误：类型错误" + orderDetail.getStatus());
            }

        }
        return amount;
    }

    /**
     * 冠军金额计算
     *
     * @param order
     * @return
     */
    private BigDecimal calChampionProfit(CrownOrder order) {
        CrownOrderDetail orderDetail = order.getDetails().get(0);
        BigDecimal amount = order.getAmount();
        BigDecimal odds = orderDetail.getOdds();
        return amount.multiply(odds);
    }
}
